package math.exact;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;

import math.ComplexNumber;

public class Complex implements ComplexNumber {

	private Rational real;
	private Rational imag;

	public Complex(Rational real) {
		this.real = real;
		this.imag = new Rational(BigInteger.ZERO);
	}

	public Complex(Rational real, Rational imag) {
		this.real = real;
		this.imag = imag;
	}

	@Override
	public String toString() {
		if (imag.getNumerator().equals(BigInteger.ZERO))
			return real.toString();
		boolean negative = imag.getNumerator().compareTo(BigInteger.ZERO) < 0;
		return real.toString() + (negative ? "" : "+") + imag.toString() + "i";
	}

	@Override
	public boolean equals(Object other) {
		if (!(other instanceof Complex))
			return false;
		return real.equals(((Complex) other).real)
				&& imag.equals(((Complex) other).imag);
	}

	public Complex add(Complex x) {
		return new Complex(real.add(x.real), imag.add(x.imag));
	}

	public Complex subtract(Complex x) {
		return new Complex(real.subtract(x.real), imag.subtract(x.imag));
	}

	public Rational getReal() {
		return real;
	}

	public Rational getImag() {
		return imag;
	}

	@Override
	public math.inexact.Complex toInexact() {
		return new math.inexact.Complex(inexact(real), inexact(imag));
	}

	private BigDecimal inexact(Rational r) {
		BigDecimal realNum = new BigDecimal(r.getNumerator());
		BigDecimal realDenom = new BigDecimal(r.getDenominator());
		return realNum.divide(realDenom, MathContext.DECIMAL128);
	}

	@Override
	public ComplexNumber negate() {
		Rational negativeReal = new Rational(real.getNumerator().negate(),
				real.getDenominator());
		Rational negativeImag = new Rational(imag.getNumerator().negate(),
				imag.getDenominator());
		return new Complex(negativeReal, negativeImag);
	}

}
